package log

import (
	hertzzap "gitee.com/byx_darwin/uptrace-opentelemetry/log/hertz"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
	"time"
)

func NewHertzLog(logConfig Config) {
	opts := make([]Option, 0, 8)
	opts = append(opts, WithPath(logConfig.Path))
	opts = append(opts, WithMaxSize(logConfig.MaxSize))
	opts = append(opts, WithMaxBackups(logConfig.MaxBackups))
	opts = append(opts, WithMaxAge(logConfig.MaxAge))
	opts = append(opts, WithCompress(logConfig.Compress))
	opts = append(opts, WithOutputMode(logConfig.OutputMode))
	opts = append(opts, WithRotationDuration(time.Duration(logConfig.RotationDuration)))
	opts = append(opts, WithSuffix(logConfig.Suffix))
	config := DefaultOptionConfig()
	for _, opt := range opts {
		opt.apply(config)
	}
	dynamicLevel := zap.NewAtomicLevel()
	dynamicLevel.SetLevel(zap.DebugLevel)
	coreConfigs := make([]hertzzap.CoreConfig, 0)
	switch config.outputMode {
	case 1:
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewConsoleEncoder(pkgEncoderConfig()),
			Ws:  zapcore.AddSync(os.Stdout),
			Lvl: dynamicLevel,
		})
	case 2:
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/all/app", config),
			Lvl: zap.NewAtomicLevelAt(zapcore.DebugLevel),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/debug/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.DebugLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/info/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.InfoLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/warn/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.WarnLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/error/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.ErrorLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/panic/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev >= zap.DPanicLevel
			}),
		})
	case 3:
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewConsoleEncoder(pkgEncoderConfig()),
			Ws:  zapcore.AddSync(os.Stdout),
			Lvl: dynamicLevel,
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/all/app", config),
			Lvl: zap.NewAtomicLevelAt(zapcore.DebugLevel),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/debug/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.DebugLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/info/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.InfoLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/warn/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.WarnLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/error/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev == zap.ErrorLevel
			}),
		})
		coreConfigs = append(coreConfigs, hertzzap.CoreConfig{
			Enc: zapcore.NewJSONEncoder(pkgEncoderConfig()),
			Ws:  NewWriteSyncer("/panic/app", config),
			Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
				return lev >= zap.DPanicLevel
			}),
		})
	}
	logger := hertzzap.NewLogger(hertzzap.WithCores(coreConfigs...),
		hertzzap.WithTraceMinSpanLevel(Level(logConfig.MinSpanLevel).ZapLevel()),
		hertzzap.WithTraceErrorSpanLevel(Level(logConfig.ErrorSpanLevel).ZapLevel()),
		hertzzap.WithRecordStackTraceInSpan(logConfig.RecordStack),
		//	hertzzap.WithZapOptions(zap.AddCaller(), zap.AddCallerSkip(3)), // 行号
	)
	defer func(logger *hertzzap.Logger) {
		err := logger.Sync()
		if err != nil {
			logger.Error(err)
		}
	}(logger)
	hlog.SetLogger(logger)
	hlog.SetLevel(Level(logConfig.MinSpanLevel).HLogLevel())
}
